package com.gexiaobao.pigeon.ui.pilot.fragment

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.Gravity
import android.view.inputmethod.EditorInfo
import android.widget.LinearLayout
import android.widget.ListPopupWindow
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener
import androidx.recyclerview.widget.LinearLayoutManager
import cn.qqtheme.framework.picker.OptionPicker
import cn.qqtheme.framework.widget.WheelView
import com.gexiaobao.pigeon.R
import com.gexiaobao.pigeon.app.base.BaseFragment
import com.gexiaobao.pigeon.app.ext.Constant
import com.gexiaobao.pigeon.app.ext.hideSoftKeyboard
import com.gexiaobao.pigeon.app.ext.init
import com.gexiaobao.pigeon.app.ext.initFooter
import com.gexiaobao.pigeon.app.ext.loadListData
import com.gexiaobao.pigeon.app.ext.loadServiceInit
import com.gexiaobao.pigeon.app.ext.showLoading
import com.gexiaobao.pigeon.app.model.bean.GatherListResponse
import com.gexiaobao.pigeon.app.model.bean.SignDeviceListResponse
import com.gexiaobao.pigeon.app.util.JWebSocketClient
import com.gexiaobao.pigeon.app.util.KvUtils
import com.gexiaobao.pigeon.app.util.RxToast
import com.gexiaobao.pigeon.app.util.Util
import com.gexiaobao.pigeon.app.weight.recycleview.SpaceItemDecoration
import com.gexiaobao.pigeon.databinding.FragmentSignPigeonDetailBinding
import com.gexiaobao.pigeon.ui.adapter.MyAdapter
import com.gexiaobao.pigeon.ui.adapter.SignUpTrainingDetailAdapter
import com.gexiaobao.pigeon.ui.dialog.RxDialogInputPigeon
import com.gexiaobao.pigeon.ui.view.CustomToast
import com.gexiaobao.pigeon.viewmodel.ReleaseMissionViewModel
import com.kingja.loadsir.core.LoadService
import me.hgj.jetpackmvvm.ext.util.setOnclickNoRepeat
import me.hgj.jetpackmvvm.util.LogUtils
import org.java_websocket.handshake.ServerHandshake
import org.json.JSONObject
import java.net.URI


/**
 * @Author      : hxw
 * @Date        : 2023/6/1 11:38
 * @Describe    : 放飞员-集鸽明细
 */
class FragmentSignPigeonDetail : BaseFragment<ReleaseMissionViewModel, FragmentSignPigeonDetailBinding>() {
    private var mPassId: String = ""

    private val mAdapter: SignUpTrainingDetailAdapter by lazy { SignUpTrainingDetailAdapter(arrayListOf()) }
    private lateinit var loadsir: LoadService<Any>
    private var qStr: String = ""
    private var imsi: String = ""
    private var mRingId: String = ""
    private var mSelectedIndex: Int = 0
    private var isWebSocketRequest = false
    private lateinit var client: JWebSocketClient

    private var listPopupWindow: ListPopupWindow? = null
    private val mList: MutableList<String> = mutableListOf()
    private var mSearchType = ""

    private var handler = @SuppressLint("HandlerLeak")
    object : Handler() {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            if (msg.data != null) {
                val bundle = msg.data
                val message = bundle.getString("msg").toString()
                val ringId = bundle.getString("ringId").toString()
                if (message.isNotEmpty()) {
                    RxToast.showToast(message)
                    return
                }
                isWebSocketRequest = true
                mViewModel.getGatherList(true, mPassId, qStr, imsi, mRingId)
                val tvImsi = mViewModel.deviceName.get().trim()
                val imsi = bundle.getString("imsi").toString()
                if (imsi == tvImsi) {
                    showToastRingNum(context, ringId)
                }
            }
        }
    }

    override fun initView(savedInstanceState: Bundle?) {
        mDatabind.viewmodel = mViewModel
        mSearchType = getString(R.string.search_by_foster)
        mDatabind.includeSearch.editQuery.hint = "请输入鸽主名或棚号"
        mPassId = requireArguments().getString("passId").toString()
        mDatabind.layoutList.swipeRecyclerView.init(LinearLayoutManager(context), mAdapter).let {
            it.addItemDecoration(SpaceItemDecoration(0, Util.dp2px(context, 0f)))
            it.initFooter {
                searchData(false)
            }
        }
        initPopup()

        listPopupWindow?.setOnItemClickListener { _, _, position, _ ->
            if (position == 0) {
                mDatabind.includeSearch.editQuery.hint = "请输入鸽主名或棚号"
            } else {
                mDatabind.includeSearch.editQuery.hint = "请输入足环号"
            }
            mSearchType = mList[position]
            mDatabind.includeSearch.tvSearchType.text = mSearchType
            mList.add(0, mList.removeAt(position))
            listPopupWindow!!.dismiss()
        }

        //状态页配置
        loadsir = loadServiceInit(mDatabind.layoutList.swipeRefreshLayout) {
            searchData(true)
        }

        searchData(false)

        mDatabind.layoutList.swipeRefreshLayout.init {
            searchData(true)
        }

        mDatabind.includeSearch.editQuery.addTextChangedListener {
            mDatabind.includeSearch.ivClose.isVisible = it.toString().isNotEmpty()
        }

        mAdapter.addChildClickViewIds(R.id.tv_item_sign_up_pigeon_foster_name)
        mAdapter.addChildClickViewIds(R.id.tv_item_sign_up_pigeon_member_num)
        mAdapter.setOnItemChildClickListener { _, view, position ->
            when (view.id) {
                R.id.tv_item_sign_up_pigeon_foster_name -> {
                    imsi = getImsi()
                    mRingId = ""
                    qStr = mAdapter.data[position].fosterName
                    mViewModel.getGatherList(true, mPassId, qStr, imsi, mRingId)
                }

                R.id.tv_item_sign_up_pigeon_member_num -> {
                    qStr = mAdapter.data[position].memberNum
                    imsi = getImsi()
                    mRingId = ""
                    mViewModel.getGatherList(true, mPassId, qStr, imsi, mRingId)
                }
            }
            mViewModel.etSearchContent.set(qStr)
        }

        mDatabind.includeSearch.editQuery.setOnEditorActionListener { _, i, _ ->
            when (i) {
                EditorInfo.IME_ACTION_SEARCH ->
                    searchData(true)

                else -> {}
            }
            false
        }

        if (!::client.isInitialized) {
            initWebSocket()
        } else if (!client.isOpen) {
            reconnectWs()//进入页面发现断开开启重连
        }
    }

    private fun searchData(isRefresh: Boolean) {
        if (mSearchType == "搜鸽主") {
            qStr = mDatabind.includeSearch.editQuery.text.toString().trim()
            mRingId = ""
        } else {
            mRingId = mDatabind.includeSearch.editQuery.text.toString().trim()
            qStr = ""
        }
        hideSoftKeyboard(activity)
        imsi = getImsi()
        if (isRefresh) loadsir.showLoading()
        mViewModel.getGatherList(isRefresh, mPassId, qStr, imsi, mRingId)
    }

    private fun initPopup() {
        mList.add(getString(R.string.search_by_foster))
        mList.add(getString(R.string.search_by_ringId))
        /** 初始化ListPopupWindow，适配 */
        listPopupWindow = ListPopupWindow(requireContext())
        val adapter = MyAdapter(requireContext(), mList)
        listPopupWindow?.setAdapter(adapter)
        listPopupWindow?.anchorView = mDatabind.includeSearch.llSearchType//设置ListPopupWindow的锚点，关联mButton位置
        listPopupWindow?.width = LinearLayout.LayoutParams.WRAP_CONTENT
        listPopupWindow?.height = LinearLayout.LayoutParams.WRAP_CONTENT
        listPopupWindow?.isModal = true
    }

    /**
     * 开启重连
     */
    private fun reconnectWs() {
        mHandler.removeCallbacks(heartBeatRunnable)
        object : Thread() {
            override fun run() {
                try {
                    LogUtils.debugInfo("开启重连", "")
                    client.reconnectBlocking()
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }
        }.start()
    }

    /**
     * 断开连接
     */
    private fun closeConnect() {
        try {
            //关闭websocket
            if (::client.isInitialized) {
                client.close()
            }
            //停止心跳
            mHandler.removeCallbacksAndMessages(null)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

    //    -------------------------------------websocket心跳检测------------------------------------------------
    private val heartbeat: Long = (10 * 1000).toLong()//每隔10秒进行一次对长连接的心跳检测
    private val mHandler = Handler()
    private val heartBeatRunnable: Runnable = object : Runnable {
        override fun run() {
            if (::client.isInitialized) {
                if (client.isClosed) {
                    LogUtils.debugInfo("心跳包检测websocket连接状态1")
                    reconnectWs() //心跳机制发现断开开启重连
                } else {
                    LogUtils.debugInfo("心跳包检测websocket连接状态2")
//                    sendMsg("Heartbeat")
                }
            } else {
                LogUtils.debugInfo("心跳包检测websocket连接状态重新连接", "")
                //如果client已为空，重新初始化连接
                initWebSocket()
            }
            //每隔一定的时间，对长连接进行一次心跳检测
            mHandler.postDelayed(this, heartbeat)
        }
    }


    private fun initWebSocket() {
        val uri = URI.create(Constant.SOCKET_URL_RACE + "/r/v1/gather/createWebSocket?imsi=$imsi&passId=$mPassId")
        client = object : JWebSocketClient(uri) {
            override fun onMessage(message: String) {
                super.onMessage(message)
                if (message != "Heartbeat") {
                    LogUtils.debugInfo("websocket收到消息：$message")
                    if (message.isNotEmpty()) {
                        val ringId = JSONObject(message).getString("ringId")
                        val msg = JSONObject(message).getString("msg")
                        val imsi = JSONObject(message).getString("imsi")
                        val mMessage = Message()
                        val bundle = Bundle()
                        bundle.putString("msg", msg)
                        bundle.putString("ringId", ringId)
                        bundle.putString("imsi", imsi)
                        mMessage.data = bundle
                        handler.sendMessage(mMessage)
                    }
                }
            }

            override fun onOpen(handshakedata: ServerHandshake) {
                super.onOpen(handshakedata)
                LogUtils.debugInfo("websocket连接成功")
            }

            override fun onError(ex: Exception) {
                super.onError(ex)
                LogUtils.debugInfo("websocket连接错误：$ex")
            }

            override fun onClose(code: Int, reason: String, remote: Boolean) {
                super.onClose(code, reason, remote)
                if (code != 1000) {
                    reconnectWs() //意外断开马上重连
                }
                LogUtils.debugInfo("websocket断开连接：·code:$code·reason:$reason·remote:$remote")
            }
        }
        //设置超时时间
        client.connectionLostTimeout = 30 * 1000
        object : Thread() {
            override fun run() {
                try {
                    /** connectBlocking多出一个等待操作，会先连接再发送，否则未连接发送会报错 */
                    client.connectBlocking()
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }
        }.start()
    }

    fun showToastRingNum(context: Context?, text: String?) {
        val customToast = CustomToast(context)
        customToast.setText(text)
        customToast.duration = Toast.LENGTH_LONG
        customToast.setGravity(Gravity.CENTER, 0, 0)
        customToast.show()
    }

    private fun getImsi(): String {
        return if (mViewModel.deviceName.get() == "全部") "" else mViewModel.deviceName.get()
    }

    override fun onBindViewClick() {
        super.onBindViewClick()
        setOnclickNoRepeat(
            mDatabind.tvChooseDevice,
            mDatabind.includeSearch.tvSearch,
            mDatabind.includeSearch.llSearchType,
            mDatabind.includeSearch.ivClose,
            mDatabind.llAllData
        ) {
            when (it) {
                mDatabind.llAllData -> searchAllData()
                mDatabind.includeSearch.ivClose -> searchAllData()
                mDatabind.includeSearch.llSearchType -> listPopupWindow?.show()
                mDatabind.tvChooseDevice -> {
                    val orgId = KvUtils.decodeInt(Constant.ORGANIZATION_ID).toString()
                    showLoading(getString(R.string.loading))
                    mViewModel.getDeviceList(orgId)
                }

                mDatabind.includeSearch.tvSearch -> searchData(true)
            }
        }
    }

    private fun searchAllData() {
        mDatabind.includeSearch.editQuery.setText("")
        qStr = ""
        mRingId = ""
        searchData(true)
    }

    private fun showInputNumPigeonDialog() {
        val dialog = RxDialogInputPigeon(context)
        dialog.setSureListener {
            dialog.dismiss()
        }
        dialog.setCanceledOnTouchOutside(false)
        dialog.setFullScreenWidth()
        dialog.show()
    }

    override fun createObserver() {
        super.createObserver()
        mViewModel.trainingSignUpDetailListResult.observe(viewLifecycleOwner) {
            val data = GatherListResponse(total = it.total)
            mDatabind.data = data
            mAdapter.setTotal(it.total)
            loadListData(it, mAdapter, loadsir, mDatabind.layoutList.swipeRecyclerView, mDatabind.layoutList.swipeRefreshLayout)
        }

        mViewModel.deviceList.observe(viewLifecycleOwner) {
            if (!it.isEmpty()) {
                showDevicePicker(it.info)
            }
        }
    }

    private fun showDevicePicker(listData: ArrayList<SignDeviceListResponse.DataList>?) {
        val flyKey: ArrayList<String> = arrayListOf()
        flyKey.add(0, "全部")
        if (listData != null && listData.size != 0) {
            for (item in listData) {
                flyKey.add(item.imsi)
            }
        }

        val picker = OptionPicker(activity, flyKey)
        val params = picker.window.attributes
        params.width = activity?.windowManager?.defaultDisplay!!.width
        picker.setCanceledOnTouchOutside(false)
        picker.setDividerRatio(WheelView.DividerConfig.FILL)
        //设置分隔阴影颜色及透明度
        context?.let { ContextCompat.getColor(it, R.color.bg_light_bllue) }?.let { picker.setShadowColor(it, 40) }//R.color.bg_light_bllue
        picker.selectedIndex = mSelectedIndex
        picker.setCycleDisable(true)
        picker.setTitleText("请选择设备")
        picker.setTitleTextColor(Color.BLACK)
        picker.setTitleTextSize(18)
        picker.setSubmitText("确认")
        picker.setSubmitTextSize(17)
        context?.let { ContextCompat.getColor(it, R.color.bg_light_bllue) }?.let { picker.setSubmitTextColor(it) }//确定按钮文字颜色
        picker.setCancelText("取消")
        picker.setCancelTextSize(17)
        context?.let { ContextCompat.getColor(it, R.color.bg_light_bllue) }?.let { picker.setCancelTextColor(it) }//取消按钮文字颜色
        picker.setTextSize(18)
        picker.setLineSpaceMultiplier(3.0F)
        picker.setOnOptionPickListener(object : OptionPicker.OnOptionPickListener() {
            override fun onOptionPicked(index: Int, item: String) {
                mSelectedIndex = index
                mViewModel.deviceName.set(item)
                imsi = if (item == "全部") {
                    ""
                } else {
                    item
                }
                searchData(true)
            }
        })
        picker.show()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        closeConnect()
        if (::client.isInitialized) {
            client.close()
        }
    }

    companion object {

        fun newInstance(passId: String): FragmentSignPigeonDetail {
            val fragment = FragmentSignPigeonDetail()
            val bundle = Bundle()
            bundle.putString("passId", passId)
            fragment.arguments = bundle
            return fragment
        }
    }
}